﻿#include "pch.h"
#include "MyClass.h"
#include <functional>
#include <future>  
#include <iostream>  
void MyClass::AddTrayIcon() 
{
	m_hIcon = LoadIcon(CPaintManagerUI::GetInstance(), MAKEINTRESOURCE(IDR_MAINFRAME));

	memset(&m_trayIcon, 0, sizeof(NOTIFYICONDATA));
	m_trayIcon.cbSize = sizeof(NOTIFYICONDATA);
	m_trayIcon.uID = 1;
	m_trayIcon.hIcon = m_hIcon;
	m_trayIcon.hWnd = m_hWnd;
	lstrcpy(m_trayIcon.szTip, _T("Msg"));
	m_trayIcon.uCallbackMessage = WM_TRAYMESSAGE;
	m_trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
	Shell_NotifyIcon(NIM_ADD, &m_trayIcon);
}


MyClass::MyClass()
{

}

MyClass::~MyClass()
{
}

LRESULT MyClass::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	bHandled = FALSE;
	return 0;
}

LRESULT MyClass::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	if (uMsg == WM_NCRBUTTONUP)
	{
		POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
		::ScreenToClient(*this, &pt);

		RECT rcClient;
		::GetClientRect(*this, &rcClient);

		RECT rcCaption = m_PaintManager.GetCaptionRect();
		if (pt.x >= rcClient.left && pt.x < rcClient.right && pt.y >= rcClient.top && pt.y < rcCaption.bottom)
			m_PaintManager.SendNotify(m_pWndTitle, DUI_MSGTYPE_MENU, 0, 0);

	}

	if (uMsg == WM_TRAYMESSAGE)
	{
		if (wParam == 1 && lParam == WM_RBUTTONUP)
		{
			::SetForegroundWindow(this->m_hWnd);

			CMenuWnd* pMenu = new CMenuWnd;
			DuiLib::CPoint point(0, 0);
			GetCursorPos(&point);
			point.y = 500;
			pMenu->Init(NULL, _T("Menu_Main.xml"), point, &m_PaintManager, &m_MenuCheckInfo, true);

			::PostMessage(m_hWnd, WM_NULL, 0, 0);
		}
		
	}

	if (uMsg == WM_CLOSE)
	{
		Shell_NotifyIcon(NIM_DELETE, &m_trayIcon);
		DestroyWindow(m_hWnd);
	}

	if (uMsg == WM_DESTROY)
		PostQuitMessage(0);

	bHandled = false;
	return 0;
}

void MyClass::Test123()
{
	int a = 1;
}

CDuiString MyClass::GetSkinFile()
{
	return _T("MainSkin.xml");
}

LPCTSTR MyClass::GetWindowClassName(void) const
{
	return LPCTSTR("UIMainFrame");
}

void MyClass::Notify(TNotifyUI& msg)
{
	CString strName = static_cast<CString>(msg.pSender->GetName());
	if (msg.sType == _T("menu"))
	{
		if (strName == _T("MainWndTitle"))
		{
			CMenuWnd* pMenu = new CMenuWnd;
			DuiLib::CPoint point(0, 0);
			GetCursorPos(&point);
			pMenu->Init(NULL, _T("Menu_Main.xml"), point, &m_PaintManager, &m_MenuCheckInfo);
		}
	}

	if (msg.sType == _T("click"))
	{
		static bool MaxMin = false;
		if (strName == _T("MyClose"))
			Close();
		else if (strName == _T("MyMinWin"))
			SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
		else if (strName == _T("MyMaxWin"))
			(MaxMin = !MaxMin) ? SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0) : SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0);
		else if (strName == _T("ins"))
			OnBtnClickins(msg);
		else if (strName == _T("MyEDIT"))
			OnBtnEdit(msg);
		else if (strName == _T("MyDelete"))
			OnBtnDelete(msg);
		else if (strName == _T("TopBof"))
			OnBtnTopAndBof(msg);
		else if (strName == _T("NewWin"))
			OnNewWin(msg);
		else if (strName == _T("InsNewWin"))
			OnBtnClickinsWin(msg);
	}

	if (msg.sType == _T("itemdbclick"))
	{
		if (strName == _T("571993"))
		{
			OnBtnTreeSele(msg);
		}
	}

	if (msg.sType == _T("selectchanged")) 
	{
		if (strName == _T("option1")) 
			m_pTabLayout->SelectItem(0);
		else if (strName == _T("option2")) 
			m_pTabLayout->SelectItem(1);
		else if (strName == _T("option3"))
			m_pTabLayout->SelectItem(2);
	}
	__super::Notify(msg);
}


void MyClass::TraverseDirectory(CString& path, int indentLevel)
{
	
	WIN32_FIND_DATA findFileData;
	/*
		第一个参数是目录名称，通常使用通配符（*）来指定搜索模式。
		第二个参数是一个指向 WIN32_FIND_DATA 结构体的指针，用于接收找到的文件或目录的属性信息。
		返回值：如果函数成功，则返回一个有效的搜索句柄；如果失败，则返回INVALID_HANDLE_VALUE。
	*/
	HANDLE hFind = FindFirstFile((path + _T("\\*")), &findFileData);

	if (hFind == INVALID_HANDLE_VALUE)
	{
		glog(<< _T("未能在目录中找到第一个文件 ") << path << '\n')
		return;
	}

	CTreeViewUI* pTreeView = static_cast<CTreeViewUI*>(m_PaintManager.FindControl(_T("MyTreeView")));
	CString strCount;
	do
	{
		// 跳过 .和 .. 目录  strcmp  wcscmp
		if (wcscmp(findFileData.cFileName, _T(".")) == 0 || wcscmp(findFileData.cFileName, _T("..")) == 0)
			continue;

		CString fullPath = path + _T("\\") + findFileData.cFileName;

		
		// FILE_ATTRIBUTE_DIRECTORY 表示找到的文件是一个【目录】
		if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{
			//如果它是一个目录，递归遍历它
			glog(<< _T("目录 ") << fullPath << '\n')
			CTreeNodeUI* temp = new CTreeNodeUI;
			strCount.Format(_T("%d"), indentLevel);
			temp->SetName(strCount);
			temp->SetMinHeight(30);

			strCount.Format(_T("%d-%d"), indentLevel, indentLevel);
			temp->GetCheckBox()->SetName(strCount);
			temp->GetCheckBox()->SetBkImage(_T(".\\img\\mor.png"));
			temp->GetCheckBox()->SetMaxWidth(30);

			strCount.Format(_T("%d-%d-%d"), indentLevel, indentLevel, indentLevel);
			temp->GetFolderButton()->SetName(strCount);
			temp->GetFolderButton()->SetBkImage(_T(".\\img\\CloseFile.png"));

			if (temp->GetCheckBox())
				temp->GetCheckBox()->OnNotify += MakeDelegate(this, &MyClass::OnBtnChBox);

			// 查找最后一个反斜杠的位置  
			int pos = fullPath.ReverseFind('\\');

			// 如果找到了反斜杠，则截取它之后的所有字符  
			CString result;
			if (pos != -1)
				result = fullPath.Mid(pos + 1);

			temp->GetItemButton()->SetText(result);

			if(indentLevel ==0)
				pTreeView->Add(temp);
			else
			{
				CString temp11;
				temp11.Format(_T("%d"), indentLevel-1);
				CTreeNodeUI* pTreeView11 = static_cast<CTreeNodeUI*>(m_PaintManager.FindControl(temp11));
				if(pTreeView11)
					pTreeView11->Add(temp);
			}
			
			TraverseDirectory(fullPath, indentLevel +1);
		}
		else
		{
			// 如果它是一个文件，打印它的名字 
			glog(<< _T("文件 ") << fullPath << '\n')
			strCount.Format(_T("%d"), indentLevel-1);
			CTreeNodeUI* pTreeView11 = static_cast<CTreeNodeUI*>(m_PaintManager.FindControl(strCount));
			CTreeNodeUI* TempFile = new CTreeNodeUI;
			// 查找最后一个反斜杠的位置  
			int pos = fullPath.ReverseFind('\\');

			// 如果找到了反斜杠，则截取它之后的所有字符  梳理设备号规则
			CString result;
			if (pos != -1)
				result = fullPath.Mid(pos + 1);
			
			strCount.Format(_T("%d"), indentLevel);
			TempFile->SetName(strCount);
			TempFile->GetItemButton()->SetText(result);
			TempFile->SetMinHeight(30);

			strCount.Format(_T("%d-%d"), indentLevel, indentLevel);
			TempFile->GetCheckBox()->SetName(strCount);
			TempFile->GetCheckBox()->SetBkImage(_T(".\\img\\mor.png"));
			TempFile->GetCheckBox()->SetMaxWidth(30);
			
			if (TempFile->GetCheckBox())
				TempFile->GetCheckBox()->OnNotify += MakeDelegate(this, &MyClass::OnBtnChBox);

			if(pTreeView11)
				pTreeView11->Add(TempFile);
		}

		/*
		FindNextFile 功能
			继续搜索：FindNextFile 函数用于在 FindFirstFile 函数返回的搜索句柄基础上继续搜索下一个文件或目录。
			参数1 ：它接受一个由 FindFirstFile 返回的搜索句柄作为输入参数。
			参数2 ：同样是一个指向WIN32_FIND_DATA结构体的指针，它返回找到的下一个文件或目录的详细信息。
			返回值：如果函数成功找到下一个文件或目录，则返回TRUE；如果没有更多文件或目录，则返回FALSE
		共同点与差异
			共同点：两者都用于遍历文件系统中的文件和目录，都需要使用 WIN32_FIND_DATA 结构体来接收文件或目录的属性信息。
			差异：FindFirstFile 用于开始搜索并返回第一个结果，而 FindNextFile 用于在已有搜索句柄的基础上继续搜索下一个结果。
		*/
	} while (FindNextFile(hFind, &findFileData) != 0);

	if (GetLastError() != ERROR_NO_MORE_FILES)
	{
		glog(<< _T("遍历文件时发生错误 ")  << '\n')
	}

	FindClose(hFind);
}

//所有初始化都在 InitWindow 里面创建
void MyClass::InitWindow()
{
	//初始化路径
	CString sInstancePath = static_cast<CString>(m_PaintManager.GetInstancePath());
	CPaintManagerUI::SetResourcePath(sInstancePath);

	//初始化托盘
	AddTrayIcon();
	
	//初始化 List 表
	pList = static_cast<CListUI*>(m_PaintManager.FindControl(_T("mylist")));
	//给 List 滚动条拖动底部注册事件回调
	CListBodyUI* pp = pList->GetCListBodyUI();
	pp->CallScrollBarBottom = std::bind(&MyClass::Test123, this);
	//默认给 List 初始化 10 条数据
	for (size_t i = 0; i < 10; i++)
	{
		if (builder.GetMarkup()->IsValid())
		{
			pEle = static_cast<CContainerUI*>(builder.Create(this, &m_PaintManager));
		}
		else
		{
			pEle = static_cast<CContainerUI*>(builder.Create(_T("list_empty_bk.xml"), (LPCTSTR)0, NULL, &m_PaintManager));
		}
		pList->Add(pEle);
	}
	
	//m_pWndTitle 是主窗口xml最外层一个节点，给主窗口所有位置增加右键菜单显示 电参考方案维护 新建电流区分系统和用户数据
	m_pWndTitle = static_cast<CHorizontalLayoutUI*>(m_PaintManager.FindControl(_T("MainWndTitle")));
	
	//初始化 Tab
	m_pTabLayout = static_cast<CTabLayoutUI*>(m_PaintManager.FindControl(_T("tablayout")));
	m_pOption1		= static_cast<COptionUI*>(m_PaintManager.FindControl(_T("option1")));
	m_pOption2		= static_cast<COptionUI*>(m_PaintManager.FindControl(_T("option2")));
	m_pOption3		= static_cast<COptionUI*>(m_PaintManager.FindControl(_T("option3")));

	//创建新窗口 m_NewWin 的时候，不能在新窗口构造函数里面创建，或者当前 MyClass 构造函数里面创建 m_NewWin
	//必须MyClass主窗口初始化完后才可以
	m_NewWin.Create(NULL, NULL, UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
	::ShowWindow(m_NewWin.GetHWND(), SW_HIDE);

	//初始化 TreeNode 节点数据
	CString directoryPath = _T("E:\\V8\\bin\\Solution"); // 修改为你的目录路径  

	int a= std::thread::hardware_concurrency();//获取 cpu 核数
	auto future = std::async(std::launch::async, [this, &directoryPath]() 
	{
		TraverseDirectory(directoryPath);
	});
}

bool  MyClass::OnBtnChBox(void* msg)
{
	TNotifyUI* TempMsg = (TNotifyUI*)msg;
	if (TempMsg->sType == _T("click"))
	{
		//所有的树节点处理逻辑都一样，只需要获取 TempMsg->pSender->GetName() 名字 ID 来做处理，
		if (TempMsg->pSender->GetName() == _T("1993"))
		{
			CCheckBoxUI* obj = (CCheckBoxUI*)TempMsg->pSender;
			if (!obj->GetCheck())
			{
				obj->SetBkImage(_T(".\\img\\goux.png"));
				obj->SetCheck(FALSE);
			}
			else
			{
				obj->SetBkImage(_T(".\\img\\mor.png"));
				obj->SetCheck(TRUE);
			}
		}
	}

	return 0;
}

void MyClass::OnBtnTreeSele(TNotifyUI& msg)
{
	CTreeNodeUI* p = static_cast<CTreeNodeUI*>(msg.pSender);
	p->GetItemButton()->SetText(_T("9527"));
}

void MyClass::OnBtnTopAndBof(TNotifyUI& msg)
{
	CGifAnimUI* m_bof = static_cast<CGifAnimUI*>(m_PaintManager.FindControl(_T("gif")));
	if (msg.pSender->GetText() == _T("暂停"))
	{
		msg.pSender->SetText(_T("播放")) ;
		m_bof->PauseGif();
	}
	else if (msg.pSender->GetText() == _T("播放"))
	{
		msg.pSender->SetText(_T("暂停"));
		m_bof->PlayGif();
	}
}

void MyClass::OnNewWin(TNotifyUI& msg)
{
	::ShowWindow(m_hWnd, SW_HIDE);
	m_NewWin.CenterWindow();
	m_NewWin.ShowModal();
}



void MyClass::OnBtnClickinsWin(TNotifyUI& msg)
{
	m_pWndTitle->RemoveAll();
	CContainerUI* pEle;
	if (builder1.GetMarkup()->IsValid())
	{
		pEle = static_cast<CContainerUI*>(builder1.Create(this, &m_PaintManager));
	}
	else
	{
		pEle = static_cast<CContainerUI*>(builder1.Create(_T("NewWin.xml"), (LPCTSTR)0, NULL, &m_PaintManager));
	}
	m_pWndTitle->Add(pEle);
}

void MyClass::OnBtnClickins(TNotifyUI& msg)
{
	if (builder.GetMarkup()->IsValid())
	{
		pEle = static_cast<CContainerUI*>(builder.Create(this, &m_PaintManager));
		pList->Add(pEle);
	}
}

void MyClass::OnBtnDelete(TNotifyUI& msg)
{
	// 获取事件发送者控件的父控件 ,这里一直从xml内到外循环查找，直到找到顶层父类是 ListContainerElement name="list_item"
	CControlUI* pParent = msg.pSender->GetParent();
	while (pParent->GetName() != _T("list_item"))
		pParent = pParent->GetParent();

	CListContainerElementUI* pListSub = (CListContainerElementUI*)pParent;
	if(pListSub)
		pList->Remove(pListSub);
}

void MyClass::OnBtnEdit(TNotifyUI& msg)
{
	CControlUI* pParent = msg.pSender->GetParent();
	while (pParent->GetName() != _T("list_item"))
		pParent = pParent->GetParent();

	CListContainerElementUI* pListSub = (CListContainerElementUI*)pParent;
	CLabelUI* pLis1t = static_cast<CLabelUI*>(pListSub->FindSubControl(_T("1994")));
		
	pLis1t->SetText(_T("123"));
}